package jstm;
#if macro
import haxe.macro.Expr;
import haxe.macro.Context;
import haxe.macro.Type;
#end
class ClassRef<T> {
	
	//calls the static main function for the class or creates an instance when no main is available
	static function run(C) {
		if (C.main != null) C.main();
		else untyped __new__(C);
	}
	
	var name:String;
	public function runMain():Void {
		//Runtime.useType(name, run);
	}
	public function createEmptyInstance(callbck:T->Void):Void {
		
	}
	public function createInstance(callbck:T->Void,?args:Array<Dynamic>):Void {
		
	}
	public function getClass(callbck:Class<T>->Void):Void {
		//Runtime.useType(name, callbck);
	}
	
	public function new(className:String) {
		name = className;
	}
	

	@:macro public static function use(callbck:ExprRequire<Class<Dynamic>->Void>):Expr {
			trace(callbck);
		switch(Context.typeof(callbck)) {
			case TFun(args, ret):
				for (arg in args) {
					switch(arg.t) {
						case TInst(ref, types):
							trace(ref.get());
							trace(ref.toString() + types.length);
						default:
							trace(arg.t);
					}
				}
				//trace(ret);
				//var t=ref.toString().split('#').join('');
				//return Context.parse('new jstm.ClassRef<'+t+'>("'+t+'")',callbck.pos);
			default:
				Context.error('function expected', callbck.pos);
		}
		//TODO: add Array<Int> argument to specify which callback args should be instances and which should be classes
		return {expr:ECall(Context.parse('untyped jstm.Runtime.callbck',callbck.pos), [callbck]),pos:callbck.pos};
		//return Context.parse('untyped jstm.Runtime.callbck(123)',callbck.pos);
	}
	
	@:macro public static function useInstance(class_:ExprRequire<Class<Dynamic>->Void>):Expr {
		return switch(Context.typeof(class_)) {
			case TType(ref, _):
				var t=ref.toString().split('#').join('');
				Context.parse('new jstm.ClassRef<'+t+'>("'+t+'")',class_.pos);
			default:
				Context.error('type expected', class_.pos);
		}
	}
	
	@:macro public static function getRef(class_:ExprRequire<Class<Dynamic>>):Expr {
		//trace(Macros.getClassName(ClassRef));
		//return Macros.stringExpr('test');
		//return Macros.getClassNameExpr(ClassRef);
		//var t = Macros.getClassName(class_);
		//	trace(class_);
		return switch(Context.typeof(class_)) {
			case TType(ref, _):
				var t=ref.toString().split('#').join('');
				Context.parse('new jstm.ClassRef<'+t+'>("'+t+'")',class_.pos);
			default:
				Context.error('type expected', class_.pos);
		}
	}
	
}